Skip to content

feat(drive): expand count-index group-by carrier shapes (G1a/G1b/G8a-c)#3652

Merged
QuantumExplorer merged 3 commits into
v3.1-devfrom
feat/count-index-group-by-carrier-shapes
May 17, 2026
Merged

feat(drive): expand count-index group-by carrier shapes (G1a/G1b/G8a-c)#3652
QuantumExplorer merged 3 commits into
v3.1-devfrom
feat/count-index-group-by-carrier-shapes

Conversation

@QuantumExplorer
Copy link
Copy Markdown
Member

@QuantumExplorer QuantumExplorer commented May 15, 2026

Issue being fixed or feature implemented

Extends the count-index group-by surface introduced alongside #3633 with new fixture coverage for edge cases of the carrier-aggregate-on-range (ACOR) and In-fanout paths, plus the rs-drive infrastructure those fixtures exercise.

What was done?

New bench fixtures + matching rs-drive support + book chapter:

  • G1aIn on byBrand with one absent value. Proof grows by ~255 B for the absence subproof; verifier omits the absent branch from Entries.
  • G1b — high-fanout In on byBrand (|IN| = B = 100). Same shape as G1, scaled up; reveals every byBrand entry.
  • G8a — bounded carrier + bounded ACOR (range on both axes) with descending walk. Same carrier shape as G8, different op variants on both range commitments.
  • G8b / G8c — rejection shapes for the two-range carrier with group_by = [brand, color] and group_by = []. Carrier is opened only for GroupByRange + single-field group_by.

Touched code:

  • packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs — mode-detection from clauses + per-mode dispatch for the new variants.
  • packages/rs-drive/src/query/drive_document_count_query/{execute_range_count,path_query,tests}.rs and executors/range_aggregate_carrier_proof.rs — executor side.
  • packages/rs-drive/src/query/mod.rs — query plumbing.
  • packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/{mod,v0/mod}.rs — verifier side.
  • packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs — count-tree wiring needed by the new fixtures.
  • packages/rs-drive/benches/document_count_worst_case.rs — fixture bodies.
  • book/src/drive/count-index-group-by-examples.md — chapter expanded with the new G* sections (proof sizes, verified shapes, tree-walk descriptions).

How Has This Been Tested?

  • cargo test -p drive (executor + verifier paths for the new variants)
  • Bench fixture (document_count_worst_case) regenerated; proof sizes match the documented G* numbers in the book chapter.

Breaking Changes

None. Drive-internal additions on top of the v1 count surface; no wire-protocol or consensus changes.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

Summary by CodeRabbit

  • New Features

    • Added support for specifying sort order (ascending/descending) in document count queries with range-based filtering.
  • Improvements

    • Enhanced range-based document counting operations to respect specified iteration directions.
    • Improved handling of range query constraints in document counting scenarios.
  • Tests

    • Expanded test suite coverage for document count operations, including additional group-by and range query edge cases.

Review Change Stack

New count-query fixtures and the rs-drive infrastructure that proves
them:

- G1a — In on byBrand with one absent value (proof grows by ~255 B
  absence subproof; verifier omits absent branches from Entries).
- G1b — high-fanout In on byBrand (|IN| = B = 100); same shape as G1
  scaled up.
- G8a — bounded carrier + bounded ACOR (range on both axes) with
  descending walk; same carrier shape as G8 with different op
  variants on both range commitments.
- G8b/G8c — rejection shapes for the two-range carrier with
  group_by = [brand, color] and group_by = [] respectively (carrier
  is opened only for GroupByRange + single-field group_by).

Touches the dispatcher, range-aggregate carrier proof executor,
path-query builder, verify side, and contract-insert wiring for the
new count-tree variants. Book chapter updated to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added this to the v3.1.0 milestone May 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 15, 2026

📖 Book Preview built successfully.

Download the preview from the workflow artifacts.
To view locally: download the artifact, unzip, and open index.html.

Updated at 2026-05-17T02:26:42.670Z

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Warning

Rate limit exceeded

@QuantumExplorer has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 5 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 30a35880-abb2-4202-b738-6b9ecea3b0ac

📥 Commits

Reviewing files that changed from the base of the PR and between f01bd9f and 516be5c.

📒 Files selected for processing (5)
  • packages/rs-drive-proof-verifier/src/proof/document_count.rs
  • packages/rs-drive/benches/document_count_worst_case.rs
  • packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs
  • packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/mod.rs
  • packages/rs-sdk/src/platform/documents/count_proof_helpers.rs
📝 Walkthrough

Walkthrough

This PR modernizes the document count request API by replacing raw CBOR-encoded where/order_by values with structured typed clauses, adding range-pair canonicalization, enabling directional traversal in carrier aggregate proofs, and expanding benchmark group-by coverage.

Changes

Document Count Request API Modernization

Layer / File(s) Summary
DocumentCountRequest schema and dispatcher contract
packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs
DocumentCountRequest struct fields migrated from raw_where_value and raw_order_by_value to where_clauses: Vec<WhereClause> and order_clauses: Vec<OrderClause>; dispatcher entry point execute_document_count_request validates and canonicalizes typed clauses; documentation expanded to describe the new contract.
Range clause canonicalization
packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs
validate_and_canonicalize_where_clauses invokes new merge_same_field_range_pairs helper to combine same-field lower/upper range pairs into single between*-style clauses; validates bounds constraints and rejects invalid combinations before merging.
Left-to-right directional traversal threading
packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs, packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs, packages/rs-drive/src/query/drive_document_count_query/executors/range_aggregate_carrier_proof.rs, packages/rs-drive/src/query/drive_document_count_query/path_query.rs, packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/mod.rs, packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/v0/mod.rs
Carrier aggregate count proof generation and verification now accept and thread left_to_right: bool parameter from dispatcher through execution functions into carrier_aggregate_count_path_query, where it controls iteration direction via Query::new_with_direction; verification path reconstructs proofs with matching direction.
Benchmark expansion with typed clause integration
packages/rs-drive/benches/document_count_worst_case.rs
Benchmark added G8a/G8b/G8c group-by matrix cases with descending order-by and two-range bounds; case tuples extended with raw_order_by; count_request builder refactored to parse fixture Values into typed where_clauses and order_clauses via dispatcher helpers; proof display harness updated for new group-by shapes and order_by dimensions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • dashpay/platform#3654: Both PRs update rs-drive's document-count path to use typed where_clauses: Vec<WhereClause> / order_clauses: Vec<OrderClause> instead of raw CBOR Value inputs in drive_document_count_query/drive_dispatcher, so the clause-shaping changes are directly related.

Suggested reviewers

  • thepastaclaw
  • shumkov

Poem

🐰 Hops through the typed clause fields so clean,
Where ranges merge to between-style gleam,
Left-to-right now flows through proof and verify,
Group-by bounds tested, benchmarks fly!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: expanding count-index group-by carrier shapes with specific new shape designations (G1a/G1b/G8a-c) that are central to this PR's functionality.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/count-index-group-by-carrier-shapes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented May 15, 2026

Review Gate

Commit: 516be5c0

  • Debounce: 25m ago (need 30m)

  • CI checks: build failure: codecov/patch

  • CodeRabbit review: comment found

  • Off-peak hours: off-peak (07:51 PM PT Saturday)

  • Run review now (check to override)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/rs-drive/src/query/mod.rs (1)

784-801: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Stop silently dropping malformed orderBy clauses.

Line [789] currently uses filter_map with .ok(), so invalid orderBy entries are ignored instead of rejected. This can change query semantics silently instead of returning a syntax error.

💡 Suggested fix
-        let order_by_clauses: Vec<OrderClause> = order_by
-            .map(|id_cbor| {
-                if let Value::Array(clauses) = id_cbor {
-                    clauses
-                        .iter()
-                        .filter_map(|order_clause| {
-                            if let Value::Array(clauses_components) = order_clause {
-                                OrderClause::from_components(clauses_components).ok()
-                            } else {
-                                None
-                            }
-                        })
-                        .collect()
-                } else {
-                    Vec::new()
-                }
-            })
-            .unwrap_or_default();
+        let order_by_clauses: Vec<OrderClause> = match order_by {
+            None => Vec::new(),
+            Some(Value::Array(clauses)) => clauses
+                .iter()
+                .map(|order_clause| match order_clause {
+                    Value::Array(clauses_components) => {
+                        OrderClause::from_components(clauses_components).map_err(Error::from)
+                    }
+                    _ => Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
+                        "order clauses must be [field, \"asc\"|\"desc\"] arrays",
+                    ))),
+                })
+                .collect::<Result<Vec<_>, Error>>()?,
+            Some(_) => {
+                return Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
+                    "order clauses must be an array",
+                )));
+            }
+        };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rs-drive/src/query/mod.rs` around lines 784 - 801, The code
currently builds order_by_clauses by using filter_map(...).ok(), which silently
drops malformed orderBy entries; instead, change the logic around
OrderClause::from_components to validate every clause and return an error when
any clause fails parsing. Replace the filter_map + collect with mapping to
Result<OrderClause, _> (using OrderClause::from_components) and collect into a
Result<Vec<OrderClause>, _>, then propagate or map the error so order_by_clauses
is only produced on success; reference OrderClause::from_components,
order_by_clauses, and the matching on Value::Array to locate the change.
🧹 Nitpick comments (2)
packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs (1)

450-460: ⚡ Quick win

Document left_to_right as a proof-shaping argument.

This new parameter affects the serialized PathQuery used by prover/verifier parity, but the method docs don’t describe its behavior yet. Please add a short arg note and ordering semantics to keep this API self-describing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs`
around lines 450 - 460, Add a short doc comment to
execute_carrier_aggregate_count_with_proof explaining that the left_to_right
boolean is a proof-shaping argument that controls the ordering of entries in the
serialized PathQuery (affecting prover/verifier parity), specify which ordering
corresponds to true vs false (e.g., left-to-right vs right-to-left), and note
that this must match callers of carrier_aggregate_count_path_query to ensure
consistent proof serialization and verification across prover and verifier.
packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/mod.rs (1)

10-13: ⚡ Quick win

Update verifier docs for directional traversal.

The API now takes left_to_right, but the doc text still describes lex-ascending output unconditionally. Please align the contract text with direction-dependent ordering.

Also applies to: 32-51

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/mod.rs`
around lines 10 - 13, The doc comment for the verifier function that returns
(root_hash, per_key_counts) is out of sync with the updated API: it still claims
lex-ascending output unconditionally but the function now accepts a
left_to_right parameter. Update the function/module docs (the comment above the
carrier AggregateCountOnRange verifier in mod.rs, and the similar block
referenced at lines 32–51) to state that per_key_counts ordering depends on
left_to_right (e.g., left_to_right == true => serialized lexicographic ascending
order, left_to_right == false => serialized lexicographic descending order), and
mention the left_to_right parameter name in the contract so callers know the
ordering behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/rs-drive/benches/document_count_worst_case.rs`:
- Around line 1056-1077: The matrix row for G8a isn't actually exercising
descending walks because raw_order_by isn't threaded through the matrix runner:
update report_group_by_matrix to accept and propagate raw_order_by alongside
raw_where, ensure the MatrixCase struct/instances (the new G8a entry) include
the appropriate raw_order_by value (representing
descending/left_to_right=false), and modify drive_count_outcome (the code that
builds the request) to use the passed raw_order_by instead of Value::Null when
constructing the request so the order-sensitive path (left_to_right=false) is
truly tested.

---

Outside diff comments:
In `@packages/rs-drive/src/query/mod.rs`:
- Around line 784-801: The code currently builds order_by_clauses by using
filter_map(...).ok(), which silently drops malformed orderBy entries; instead,
change the logic around OrderClause::from_components to validate every clause
and return an error when any clause fails parsing. Replace the filter_map +
collect with mapping to Result<OrderClause, _> (using
OrderClause::from_components) and collect into a Result<Vec<OrderClause>, _>,
then propagate or map the error so order_by_clauses is only produced on success;
reference OrderClause::from_components, order_by_clauses, and the matching on
Value::Array to locate the change.

---

Nitpick comments:
In
`@packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs`:
- Around line 450-460: Add a short doc comment to
execute_carrier_aggregate_count_with_proof explaining that the left_to_right
boolean is a proof-shaping argument that controls the ordering of entries in the
serialized PathQuery (affecting prover/verifier parity), specify which ordering
corresponds to true vs false (e.g., left-to-right vs right-to-left), and note
that this must match callers of carrier_aggregate_count_path_query to ensure
consistent proof serialization and verification across prover and verifier.

In
`@packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/mod.rs`:
- Around line 10-13: The doc comment for the verifier function that returns
(root_hash, per_key_counts) is out of sync with the updated API: it still claims
lex-ascending output unconditionally but the function now accepts a
left_to_right parameter. Update the function/module docs (the comment above the
carrier AggregateCountOnRange verifier in mod.rs, and the similar block
referenced at lines 32–51) to state that per_key_counts ordering depends on
left_to_right (e.g., left_to_right == true => serialized lexicographic ascending
order, left_to_right == false => serialized lexicographic descending order), and
mention the left_to_right parameter name in the contract so callers know the
ordering behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b77c2ed8-5e9e-4952-95ee-0d33ab0e2f6d

📥 Commits

Reviewing files that changed from the base of the PR and between dfb6d84 and 54a0662.

📒 Files selected for processing (11)
  • book/src/drive/count-index-group-by-examples.md
  • packages/rs-drive/benches/document_count_worst_case.rs
  • packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs
  • packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs
  • packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs
  • packages/rs-drive/src/query/drive_document_count_query/executors/range_aggregate_carrier_proof.rs
  • packages/rs-drive/src/query/drive_document_count_query/path_query.rs
  • packages/rs-drive/src/query/drive_document_count_query/tests.rs
  • packages/rs-drive/src/query/mod.rs
  • packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/mod.rs
  • packages/rs-drive/src/verify/document_count/verify_carrier_aggregate_count_proof/v0/mod.rs

Comment thread packages/rs-drive/benches/document_count_worst_case.rs
…group-by-carrier-shapes

# Conflicts:
#	packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs
#	packages/rs-drive/src/query/mod.rs
@codecov
Copy link
Copy Markdown

codecov Bot commented May 17, 2026

Codecov Report

❌ Patch coverage is 18.18182% with 72 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.05%. Comparing base (187d46c) to head (516be5c).

Files with missing lines Patch % Lines
...ery/drive_document_count_query/drive_dispatcher.rs 24.24% 50 Missing ⚠️
...s-drive-proof-verifier/src/proof/document_count.rs 0.00% 6 Missing ⚠️
..._count/verify_carrier_aggregate_count_proof/mod.rs 0.00% 6 Missing ⚠️
.../drive_document_count_query/execute_range_count.rs 0.00% 3 Missing ⚠️
...unt/verify_carrier_aggregate_count_proof/v0/mod.rs 0.00% 3 Missing ⚠️
...t_query/executors/range_aggregate_carrier_proof.rs 0.00% 2 Missing ⚠️
...src/query/drive_document_count_query/path_query.rs 0.00% 2 Missing ⚠️

❌ Your patch check has failed because the patch coverage (18.18%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##           v3.1-dev    #3652      +/-   ##
============================================
- Coverage     88.07%   88.05%   -0.02%     
============================================
  Files          2521     2521              
  Lines        308681   308763      +82     
============================================
+ Hits         271879   271894      +15     
- Misses        36802    36869      +67     
Components Coverage Δ
dpp 88.01% <ø> (ø)
drive 87.03% <19.51%> (-0.04%) ⬇️
drive-abci 90.05% <ø> (ø)
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.17% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 53.13% <0.00%> (-0.10%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…ench matrix

- rs-drive-proof-verifier + rs-sdk: pass `left_to_right` to
  `verify_carrier_aggregate_count_proof`. The wrapper signatures
  were stale relative to the inner verifier's new directional
  contract, breaking the workspace build on macOS. SDK derives
  the direction from `request.order_by_clauses.first().ascending`
  (same pattern the distinct path uses).

- bench `document_count_worst_case::report_group_by_matrix`: add
  `raw_order_by` to `MatrixCase`, thread it through
  `drive_count_outcome`, and set the G8a row to
  `order_by_brand_desc` instead of `Value::Null`. The previous
  shape silently exercised the default ascending path, so the
  "left_to_right=false" label was misleading — flagged by
  CodeRabbit on PR #3652.

- doc-comment updates on `execute_carrier_aggregate_count_with_proof`
  and `verify_carrier_aggregate_count_proof` to call out
  `left_to_right` as a proof-shaping bit (must match prover/verifier).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@QuantumExplorer QuantumExplorer requested a review from shumkov as a code owner May 17, 2026 02:26
Copy link
Copy Markdown
Member Author

@QuantumExplorer QuantumExplorer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed

@github-actions
Copy link
Copy Markdown
Contributor

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "eab52afca7c3fbf018f04d22227809fb00c3337f3b4bd52ee9b54126ad181c1c"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

@QuantumExplorer QuantumExplorer merged commit 61bca22 into v3.1-dev May 17, 2026
22 of 23 checks passed
@QuantumExplorer QuantumExplorer deleted the feat/count-index-group-by-carrier-shapes branch May 17, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants